﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Schema;
using System.Xml.Linq;
using System.Windows.Forms;

namespace cz.muni.fi.pb138.XML
{
	/// <summary>
	/// The class provides all necessary functions to manipulate XML data to be stored in a DB
	/// </summary>
    public class XmlHelper
    {
		/// <summary>
		/// Validates the given media against the media.xsd XML schema in Resources
		/// </summary>
		/// <param name="media"><c>Media</c> class as XElement to be validated</param>
		/// <returns>true if valid; false if not</returns>
        public static bool ValidateXML(XElement media)
        {
            XmlSchemaSet schemas = new XmlSchemaSet();
            schemas.Add("", "Resources/media.xsd");

            try
            {
                XDocument docToValidate = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), media);


                docToValidate.Validate(schemas, null);

            }
            catch (XmlSchemaValidationException e)
            {
                //throw new InvalidOperationException("Can't process database file. XML is doesn't match XML Schema.", e);
                MessageBox.Show(e.Message);
                return false;
            }

            return true;
        }


        private static XNamespace aw = "http://www.xmldb.org/xupdate";
		/// <summary>
		/// Creates an XML document as string that will be sent to DB and commands the DB
		/// to append <c>element</c> at the end of all existing media
		/// </summary>
		/// <param name="element"></param>
		/// <returns>string containing the update command</returns>
        public static string CreateXUpdateAppend(XElement element)
        {

            XElement update = CreateXUpdateRoot();
            XElement action = new XElement(aw + "append",
                new XAttribute("select", "/medias"),
                new XAttribute("child", "last()"));

            XElement toAdd = new XElement(aw + "element",
                new XAttribute("name", "medium"));

            element.Elements().ToList().ForEach(x => toAdd.Add(x));
            action.Add(toAdd);

            update.Add(action);

            Console.WriteLine(update);
            return update.ToString();
        }

		/// <summary>
		/// Creates an XML document as string that will be sent to DB and commands the DB
		/// to append <c>element</c> at the end of all existing users and thus creating 
		/// a new one
		/// </summary>
		/// <param name="userName">new user name</param>
		/// <param name="password">a password of the new user</param>
		/// <returns>string containing the update command</returns>
        public static string CreateXUpdateAppendAddUser(string userName, string password)
        {

            XElement update = CreateXUpdateRoot();

            XElement person = new XElement("notimportant", new XElement("login", userName), new XElement("password", password));


            XElement action = new XElement(aw + "append",
                new XAttribute("select", "/users"),
                new XAttribute("child", "last()"));

            XElement toAdd = new XElement(aw + "element",
                new XAttribute("name", "user"));

            person.Elements().ToList().ForEach(x => toAdd.Add(x));
            action.Add(toAdd);

            update.Add(action);

            //Console.WriteLine(update);
            return update.ToString();
        }
		
		/// <summary>
		/// Creates an XML document as string that will be sent to DB and commands the DB
		/// to update certain <c>element</c>. The element is a medium to be updated and
		/// chosen is the corresponding existing medium with the same ID child
		/// </summary>
		/// <param name="element">media as <c>XElement</c> class</param>
		/// <returns>string containing the media update command</returns>
        public static string CreateXUpdateUpdate(XElement element)
        {

            XElement update = CreateXUpdateRoot();
            XElement action = new XElement(aw + "update",
                new XAttribute("select", string.Format("/medias/medium[id={0}]", (long)element.Element("id"))));


            element.Elements().ToList().ForEach(x => action.Add(x));

            update.Add(action);

            Console.WriteLine(update);
            return update.ToString();
        }


		/// <summary>
		/// Creates an XML document as string that will be sent to DB and commands the DB
		/// to remove certain <c>element</c>. The element is a medium to be removed and
		/// chosen is the corresponding existing medium with the same ID child
		/// </summary>
		/// <param name="element">medium as an <c>XElement</c> to be removed</param>
		/// <returns>string containing the media remove command</returns>
        public static string CreateXUpdateRemove(XElement element)
        {

            XElement update = CreateXUpdateRoot();
            XElement action = new XElement(aw + "remove",
                new XAttribute("select", string.Format("/medias/medium[id={0}]", (long)element.Element("id"))));

            update.Add(action);

            Console.WriteLine(update);
            return update.ToString();
        }

		/// <summary>
		/// creates the root structure of the XML document
		/// </summary>
		/// <returns>string representation of a root of an XML document</returns>
        private static XElement CreateXUpdateRoot()
        {
            XNamespace ab = "xupdate";
            XElement update = new XElement(aw + "modifications",
                new XAttribute(XNamespace.Xmlns + "xupdate", "http://www.xmldb.org/xupdate"),
                new XAttribute("version", "1.0")
            );

            return update;
        }
    }
}
